package utils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"xinmanpan/config"
)

/*
// 生成一个 16 字节（128 位）的随机密钥
	randomKey, err := GenerateRandomKey(16)
	if err != nil {
		fmt.Println("生成随机密钥失败:", err)
		return
	}

	fmt.Println("生成的随机密钥:", randomKey)

*/
// GenerateRandomKey 生成指定字节长度的随机密钥
func GenerateRandomKey(length int) (string, error) {
	if length <= 0 {
		return "", fmt.Errorf("invalid length: %d", length)
	}

	// 创建一个字节切片
	key := make([]byte, length)

	// 填充随机数据
	_, err := rand.Read(key)
	if err != nil {
		return "", fmt.Errorf("failed to generate random key: %v", err)
	}

	// 转换为十六进制字符串
	return hex.EncodeToString(key), nil
}

// 填充函数（PKCS7 填充）
func pkcs7Padding(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padText...)
}

// 去除填充函数
func pkcs7UnPadding(data []byte) []byte {
	length := len(data)
	padding := int(data[length-1])
	return data[:length-padding]
}

// AES 加密函数
func Encrypt(plainText string) (string, error) {
	key := []byte(config.AESKey)
	// 将字符串转换为字节切片
	plainTextBytes := []byte(plainText)

	// 创建 AES 密码块
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	// 填充数据，确保长度是块大小的倍数
	blockSize := block.BlockSize()
	plainTextBytes = pkcs7Padding(plainTextBytes, blockSize)

	// 创建一个初始化向量（IV）
	iv := make([]byte, blockSize)
	if _, err := rand.Read(iv); err != nil {
		return "", err
	}

	// 使用 CBC 模式加密
	mode := cipher.NewCBCEncrypter(block, iv)
	cipherText := make([]byte, len(plainTextBytes))
	mode.CryptBlocks(cipherText, plainTextBytes)

	// 返回 IV 和加密后的密文，通常 IV 是明文传输的
	// 将 IV 和密文合并为一个字符串返回
	return hex.EncodeToString(append(iv, cipherText...)), nil
}

// AES 解密函数
func Decrypt(cipherText string) (string, error) {
	key := []byte(config.AESKey)
	// 将密文从十六进制字符串转换为字节切片
	cipherTextBytes, err := hex.DecodeString(cipherText)
	if err != nil {
		return "", err
	}

	// 创建 AES 密码块
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", err
	}

	// 获取 IV 和密文
	blockSize := block.BlockSize()
	if len(cipherTextBytes) < blockSize {
		return "", errors.New("ciphertext too short")
	}

	iv := cipherTextBytes[:blockSize]
	cipherTextBytes = cipherTextBytes[blockSize:]

	// 使用 CBC 模式解密
	mode := cipher.NewCBCDecrypter(block, iv)
	plainTextBytes := make([]byte, len(cipherTextBytes))
	mode.CryptBlocks(plainTextBytes, cipherTextBytes)

	// 去除填充
	plainTextBytes = pkcs7UnPadding(plainTextBytes)

	// 返回解密后的字符串
	return string(plainTextBytes), nil
}
